<template>
  <div>
    <a-modal v-model:visible="modalVisible" :title="`${$t('osManager.taskDetail')}：${name}`" width="1200px" @cancel="fnClose">
      <template #title>
        <div class="taskName">{{ $t("osManager.taskDetail") }}：{{ name }}</div>
        <div class="recover" v-if="type === taskType.securityManage">
          <a-tooltip placement="top" :content="$t('osManager.oneClickHardeningTip')">
            <a-button class="recover-button" @click="fnExeRecoverTask" :disabled="status !== taskStatus.success.code">
              {{ $t("osManager.oneClickHardening") }}
              <QuestionCircleOutlined class="el-icon--right"/>
            </a-button>
          </a-tooltip>
        </div>
      </template>
      <div v-loading="loading" style="display: flex">
        <div style="width: 250px; margin-right: 50px" class="displayBox bigBox">
          <div class="boxTitle">{{ $t("osManager.hostOrGroup") }}</div>
          <a-input-search
            v-model:value="search"
            :placeholder="$t('osManager.enterKeyWord')"
            @search="initPage"
          />
          <a-tree :tree-data="hostList" @select="fnChooseAsset"></a-tree>
        </div>
        <div style="width: 310px" class="displayBox bigBox">
          <a-table
            size="middle"
            ref="result"
            row-key="check_id"
            v-if="type === taskType.inspection || type === taskType.securityManage"
            :row-selection="{
              type: 'radio',
              onSelect: fnChooseItem
            }"
            :data-source="showAssetTable"
            :columns="[
              {
                title: $t('osManager.result'),
                dataIndex: 'statusClass',
                key: 'statusClass',
                width: '60',
                filters,
              },
              {
                title: $t('osManager.inspectItem'),
                dataIndex: 'label',
                key: 'label',
              },
            ]"
            @current-change="fnChooseItem"
            @change="filterStatus"
            height="540"
            highlight-current-row
          >
            <template #bodyCell="{ record, column }">
              <template v-if="column.dataIndex === 'statusClass'">
                <div :class="`statusBtn ${ record[column.dataIndex] }`"></div>
              </template>
            </template >
          </a-table>
          <div v-else-if="type === taskType.infoCollect">
            <div class="boxTitle">{{ $t("osManager.collectItem") }}</div>
            <a-tree :tree-data="assetsTable" @select="fnChooseInfo" highlight-current></a-tree>
          </div>
          <div v-else>
            <div class="boxTitle">{{ $t("osManager.runningResult") }}</div>
            <div v-html="result.content" style="margin: 10px; white-space: pre-wrap" class="terminalDisplay"></div>
          </div>
        </div>
        <div
          style="width: 480px; margin-left: 50px"
          class="displayBox bigBox"
          v-if="checkItem.check_id || result.content"
        >
          <div v-if="type === taskType.inspection || type === taskType.securityManage">
            <div class="boxTitle" style="margin-bottom: 10px">
              <div style="padding: 0 10px">
                <div style="float: left">{{ checkItem.check_id }}</div>
                <div style="float: right">{{ checkItem.finished_time }}</div>
                <div style="text-align: center">{{ checkItem.label }}</div>
              </div>
            </div>
            <div style="padding: 0 10px">
              {{ $t("osManager.inspectDesc") }}:
              <div class="displayBox" style="height: 210px; margin-bottom: 10px; padding: 10px">
                <span style="white-space: pre-wrap">{{ fnGetI18nLabel(checkItem.item_description) }}</span>
                <br /><br />
                {{ $t("osManager.inspectAdvice") }}：<br />
                <span style="white-space: pre-wrap">{{ fnGetI18nLabel(checkItem.suggest) }}</span>
              </div>
              {{ $t("osManager.inspectResult") }}：
              <div class="displayBox" style="height: 180px; padding: 10px">
                <div v-html="fnGetI18nLabel(checkItem.result_info).replace(/\n/g, '<br>')"></div>
              </div>
            </div>
          </div>
          <div style="padding: 10px" v-else>
            <div v-html="result.content" style="height: 475px; overflow-y: auto; white-space: pre-line"></div>
            <a-row type="flex" justify="space-between">
              <a-button
                class="actionBtn"
                :icon="h(VerticalAlignBottomOutlined)"
                type="link"
                @click="fnDownloadFile"
              >{{ $t("osManager.downloadFile") }}</a-button
              >
              <a-pagination
                show-quick-jumper
                :show-size-changer="false"
                size="small"
                v-model:current="result.currentPage"
                :total="result.total"
              >
              </a-pagination>
            </a-row>
          </div>
        </div>
      </div>
    </a-modal>
  </div>
</template>

<script>
import { api } from '@/api';
import { getStatus, taskStatus } from './components/errorCode';
import { downloadTheFile, taskType, fnIsError } from './components';
import { VerticalAlignBottomOutlined } from '@ant-design/icons-vue'
import { h } from 'vue'
import { storeToRefs } from 'pinia'
import { useLangStore } from '@/store'
const { lang } = useLangStore()


export default {
  emits: ['close'],
  name: 'resultDetailDialog',
  props: ['isShow', 'id', 'name', 'type', 'status'],
  data() {
    return {
      taskType,
      loading: false,
      search: '',
      hostList: [],
      hostAssets: [],
      assetsTable: [],
      filterKeys: [],
      taskStatus,

      checkAsset: {},
      checkItem: {},
      result: {
        content: '',
        total: 0,
        currentPage: 1,
      },
    };
  },
  watch: {
    isShow(val) {
      if (!val) {
        return;
      }
      this.initPage();
    },
    'result.currentPage': function () {
      this.fnGetTaskResult();
    },
  },
  computed: {
    filters() {
      const list = [
        { text: this.$t('osManager.success'), value: 'success' },
        { text: this.$t('common.fail'), value: 'fail' },
        { text: this.$t('osManager.notExecute'), value: 'executing' },
      ];
      if (this.type === taskType.securityManage) {
        list.push({ text: this.$t('osManager.tobeHarden'), value: 'recoverable' });
      }
      return list;
    },
    modalVisible() {
      return this.isShow;
    },
    showAssetTable() {
      let showTable = this.assetsTable;
      if (this.filterKeys.length) {
        showTable = this.assetsTable.filter(item => this.filterKeys.indexOf(item.statusClass) > -1)
      }
      return showTable
    }
  },
  mounted() {
    if (!this.id) {
      return;
    }
    this.initPage();
  },
  methods: {
    h,
    VerticalAlignBottomOutlined,
    async initPage() {
      this.loading = true;
      this.search = '';
      this.checkItem = {};
      this.assetsTable = [];
      this.result.content = '';
      const [_, res] = await api.fnGetDetailByTaskId(this.id);
      this.hostList = this.fnFormatHostTree(res.host_groups, res.host_assets);
      this.hostAssets = res.host_assets;
      if (this.$refs.result) {
        this.$refs.result.clearFilter();
      }
      this.loading = false;
    },
    fnFormatHostTree(groups, assets) {
      const tree = [];
      Object.keys(groups).forEach(group => {
        const children = [];
        groups[group].forEach(host => {
          const id = `${group}_${host}`;
          const item = {
            title: host,
            key: id,
            id,
            nodeIndex: assets[host].node_index,
          };
          item.children = this.fnFormatAssetLeaf(assets[host], id);
          children.push(item);
        });
        tree.push({
          title: group,
          key: group,
          id: group,
          children,
        });
      });
      return tree;
    },
    fnFormatAssetLeaf(host, pId) {
      return Object.keys(host.assets).map(index => {
        const asset = host.assets[index];
        return {
          key: `${pId}_${index}`,
          assetId: Number(index),
          title: `${this.fnGetI18nLabel(asset)}_${asset.version}`,
          nodeIndex: host.node_index,
        };
      });
    },
    async fnChooseAsset(data, node) {
      if (!node.selected || node.node.children?.length) {
        return;
      }
      this.checkAsset = node.node;
      const param = {
        task_id: this.id,
        node_index: node.node.nodeIndex,
        case_index: node.node.assetId || 0,
        task_type: this.type,
      };
      const [_, res] = await api.fnQueryAssetsItem(param);
      switch (this.type) {
        case taskType.inspection:
          this.assetsTable = res.map(item => {
            item.label = this.fnGetI18nLabel(item.item_name);
            item.statusClass = getStatus(item.status).field;
            return item;
          });
          break;
        case taskType.securityManage:
          this.assetsTable = res.map(item => {
            item.label = this.fnGetI18nLabel(item.item_name);
            item.statusClass = getStatus(item.status).field;
            if (item.statusClass === 'fail' && item.recoverable) {
              item.statusClass = 'recoverable';
            }
            return item;
          });
          break;
        case taskType.infoCollect:
          this.assetsTable = this.fnFormatTree(res);
          break;
        default:
          this.result.content = res.data.join('');
          break;
      }
    },
    fnGetI18nLabel(name) {
      return lang === 'en' ? name.en : name.zh || '--';
    },
    fnFormatTree(data, path = []) {
      if (!data || !data.length) {
        return;
      }
      data.forEach(node => {
        node.path = path ? [...path, node.label] : [node.label];
        node.title = node.label;
        this.fnFormatTree(node.children, node.path);
      });

      return data;
    },
    fnChooseItem(record) {
      if (!record) {
        // 当表格置空时也会触发
        return;
      }
      this.checkItem = record;
    },
    async fnChooseInfo(file, node) {
      if (!node.selected || node.node.children?.length) {
        return;
      }
      this.checkItem = node.node;
      this.result.currentPage = 1;
      await this.fnGetTaskResult();
    },
    async fnGetTaskResult() {
      const param = {
        task_id: this.id,
        page_index: this.result.currentPage,
        item_path: this.checkItem.path,
        node_index: this.checkAsset.nodeIndex,
        case_index: this.checkAsset.assetId || 0,
      };
      this.result.content = '';
      const [_, res] = await api.fnQueryTaskResult(param);
      this.result.content = res.content;
      this.result.total = res.total_page;
    },
    filterStatus(pagination, filters, sorter, { currentDataSource }) {
      console.log(pagination, filters, sorter, currentDataSource)
      this.filterKeys = filters.statusClass || [];
    },
    async fnDownloadReport(row) {
      const [_, res] = await api.fnDownloadReportById(row.id);
      downloadTheFile(res, `${row.name}.zip`);
    },
    async fnDownloadFile() {
      const param = {
        task_id: this.id,
        page_index: this.result.currentPage,
        item_path: this.checkItem.path,
        node_index: this.checkAsset.nodeIndex,
        case_index: this.checkAsset.assetId || 0,
      };
      const [_, res] = await api.fnDownloadReport(param);
      downloadTheFile(res, `${this.checkItem.label}.txt`);
    },
    fnClose() {
      this.$emit('close');
    },
    async fnExeRecoverTask() {
      const param = {
        task_id: this.id,
        action: 'recover',
      }
      await api.fnTaskAttention(param);
      this.$parent.initPage();
    },
  },
};
</script>

<style scoped lang="less">
::v-deep {
  .taskName {
    font-size: 18px;
    display: inline-block;
    width: 1000px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .boxTitle {
    width: 100%;
    height: 39px;
    line-height: 39px;
    background-color: var(--table-head-color);
    text-align: center;
  }

  .statusBtn {
    width: 14px;
    height: 14px;
    border-radius: 14px;
    background-color: #8c939d;
  }

  .displayBox {
    border: 1px solid #d9d9d9;
    overflow-y: auto;
  }

  .bigBox {
    height: 580px;
  }

  .success {
    background-color: rgb(135, 208, 104);
  }

  .fail {
    background-color: rgb(255, 85, 0);
  }

  .recoverable {
    background-color: yellow;
  }

  .recover {
    float: right;
    margin-right: 30px;
    height: 30px;
  }
  .recover-button {
    margin-left: 20px;
  }
  .recover-description {
    margin-left: 5px;
    font-size: 10px;
  }
}
</style>
